import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.lang.Math;
/*
 * this class implments equal 
 * will be used to create histograms
 * 
 */
public class Range
{
	private double start;
	private double end;
	private char start_bracket;
	private char end_bracket;
	private int count;
	
	public Range(){
		
	}
	
	public Range( char start_bracket, double start, double end, char end_bracket){
		this.start = start;
		this.end = end;
		this.start_bracket = start_bracket;
		this.end_bracket = end_bracket;
	}
	
	public Range(char c, int chunkLow, int chunkHigh, char d, int count) {
		this.start = start;
		this.end = end;
		this.start_bracket = start_bracket;
		this.end_bracket = end_bracket;
		this.count = count;
	}
	
	public int getHeight() {
		return count;
	}

	public String toString(){
		
		String s = " "  + this.start_bracket + this.start + "," + 
				   this.end + this.end_bracket;
		return s;
	
	}
	
	public boolean equals(Range that){
		
		if ( this.end == that.end && this.start == that.end 
				&& this.start_bracket == that.start_bracket){
			return true;
		}
		return false;
	}
	
	/*
	 * given the minimum of relation and maximum of relation and bucket number, prints out arraylist
	 * of the ranged
	 */
	public static ArrayList<Range> returnRangeArray( int min, int max, int bucket){
		
		ArrayList<Range> r = new ArrayList<Range>();
		double width = (int) Math.floor( (max - min ) / bucket );
		
		// makes the array list now 
		for (int i = 0; i < bucket  ; i++) {
			// min + (i-1)* width,   min + i*width
			
			double chunklow  = (double)min + (double)i * width;
			double chunkhigh = (double)min + (double)(i+1) * width;
			
			// so now if the it is equal to last bucket number, make range both [  ]
			if ( i == bucket-1){
				r.add(new Range('[', chunklow, chunkhigh, ']'));
			}else{
				r.add(new Range('[', chunklow, chunkhigh, ')'));
			}
			
		}
		
		return r;
	}

	/*
	 * given the ArrayList of range, and the number
	 * spits out the index of the arraylist that the number belongs to
	 * return -1 if the number goes out of bound
	 */
	public static int returnIndex( ArrayList<Range> range, int number){
		int index= -1;
		Iterator<Range> rangeiter = range.iterator();
		
		// go through until i find the one in range
		while( rangeiter.hasNext()){
			Range r = rangeiter.next();
			if ( inRange(r, number)){
				return range.indexOf(r);
			}
			
		}
		return index;
	}
	
	public int getStart(){
		return (int)this.start;
	}
	
	public int getEnd(){
		return (int)this.end;
	}
	/*
	 * given the range object and number tell if it is in range.
	 */
	public static boolean inRange( Range range, int number){

		if ( number >= range.start){
			if ( range.end_bracket == ']' ){
				if (number <= range.end){
					return true;
				}
			}
			else{
				if (number < range.end){
					return true;
				}
			}
		}
		
		return false;
	}
	
	/**
	 * Whether the range's values are between two given values.
	 * @param low
	 * @param high
	 * @return
	 */
	public boolean isBetween(int low, int high) {
		return (low < start && high > end);
	}
	
	public boolean subsetRange(int r1, int r2){
		float leeway = Math.abs(r2-r1);
		leeway *= 0.01; // this is for some leeways into the range
				// range is wider                // range is smaller
		return ( (r1 >= start) && (r2 <= end)  || ( (r1<= start) && (r2>=end))
		 		 || (r1 >= (start-leeway)) && (r2 <= (end + leeway))
		 		 || (r1 <= (start+leeway)) && (r2 >= (end - leeway)));
	}
	
	// this will get the percent of the Range that tthe given input takes
	public float getPercentage(int r1, int r2){
		float rangeDiff = Math.abs((float)end -(float) start);
		float inputDiff = Math.abs((float)r2-(float)r1);
		float percent;
		if ( inputDiff > rangeDiff){
			percent =1;
		}else{
			percent = inputDiff / rangeDiff;
		}
		return percent;
	}
}
